﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;

namespace DusonFramework.Core
{
    public class Thumbnail
    {
        #region 生成缩略图
        /// <summary>
        /// 生成缩略图
        /// </summary>
        /// <param name="originalImagePath">源图路径（物理路径）</param>
        /// <param name="thumbnailPath">缩略图路径（物理路径）</param>
        /// <param name="width">缩略图宽度</param>
        /// <param name="height">缩略图高度</param>
        /// <param name="isfixed">当原始尺寸小于缩放尺寸时，true为缩放尺寸，false为原始尺寸</param>  
        public static bool MakeThumbnail(string originalImagePath, string thumbnailPath, int width, int height, bool isfixed)
        {

            Image originalImage = null;
            Image bitmap = null;
            Graphics g = null;
            try
            {
                originalImage = Image.FromFile(originalImagePath);
                int towidth = width;
                int toheight = height;

                int x = 0;
                int y = 0;
                int ow = originalImage.Width;
                int oh = originalImage.Height;

                if (!isfixed && ow < width && oh < height)
                {
                    towidth = ow;
                    toheight = oh;
                }
                else
                {
                    //如果宽缩放比例 大于 高的缩放比例
                    if ((double)ow / (double)width >= (double)oh / (double)height)
                    {
                        toheight = width * oh / ow;
                    }
                    else
                    {
                        towidth = height * ow / oh;
                    }
                }

                //Gif需要分别截取每一帧，然后再重新合成
                if (originalImage.RawFormat.Guid == ImageFormat.Gif.Guid)
                {
                    FileStream fs = new FileStream(originalImagePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                    List<int> delays = new List<int>();
                    //按帧分割
                    string guidGif = DecodeGIF(fs, out delays);
                    fs.Close();
                    //对每帧生成缩略图
                    if (!string.IsNullOrEmpty(guidGif))
                    {
                        if (!ThumbGIF(guidGif, width, height))
                        {
                            return false;
                        }
                        if (!EncodeGIF(guidGif, thumbnailPath, delays))
                        {
                            return false;
                        }
                    }
                }
                else
                {

                    //新建一个bmp图片
                    bitmap = new System.Drawing.Bitmap(towidth, toheight);

                    //新建一个画板
                    g = System.Drawing.Graphics.FromImage(bitmap);

                    //设置高质量插值法
                    g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;

                    //设置高质量,低速度呈现平滑程度
                    g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;

                    //清空画布并以透明背景色填充
                    g.Clear(Color.Transparent);

                    //在指定位置并且按指定大小绘制原图片的指定部分
                    g.DrawImage(originalImage, new Rectangle(0, 0, towidth, toheight),
                        new Rectangle(x, y, ow, oh),
                        GraphicsUnit.Pixel);


                    //以jpg格式保存缩略图
                    bitmap.Save(thumbnailPath, System.Drawing.Imaging.ImageFormat.Jpeg);
                }
                return true;
            }
            finally
            {
                if (originalImage != null)
                {
                    originalImage.Dispose();
                }
                if (bitmap != null)
                {
                    bitmap.Dispose();
                }
                if (g != null)
                {
                    g.Dispose();
                }
            }
        }
        #endregion

        #region 生成缩略图 等比缩放
        /// <summary>
        /// 生成缩略图
        /// </summary>
        /// <param name="originalImagePath">源图路径（物理路径）</param>
        /// <param name="thumbnailPath">缩略图路径（物理路径）</param>
        /// <param name="width">缩略图宽度</param>
        /// <param name="height">缩略图高度</param>
        /// <param name="isfixed">当原始尺寸小于缩放尺寸时，true为缩放尺寸，false为原始尺寸</param>
        public static void MakeThumbnail(byte[] bytes, string thumbnailPath, int width, int height, bool isfixed)
        {
            MemoryStream originalImageMs = new MemoryStream(bytes, 0, bytes.Length);
            Image originalImage = null;
            Image bitmap = null;
            Graphics g = null;
            try
            {
                originalImage = Image.FromStream(originalImageMs);
                int towidth = width;
                int toheight = height;

                int x = 0;
                int y = 0;
                int ow = originalImage.Width;
                int oh = originalImage.Height;

                if (!isfixed && ow < width && oh < height)
                {
                    towidth = ow;
                    toheight = oh;
                }
                else
                {
                    //如果宽缩放比例 大于 高的缩放比例
                    if ((double)ow / (double)width >= (double)oh / (double)height)
                    {
                        toheight = width * oh / ow;
                    }
                    else
                    {
                        towidth = height * ow / oh;
                    }
                }

                ////Gif需要分别截取每一帧，然后再重新合成
                if (originalImage.RawFormat.Guid == ImageFormat.Gif.Guid)
                {
                    List<int> delays = new List<int>();
                    //按帧分割
                    string guidGif = DecodeGIF(originalImageMs, out delays);
                    //对每帧生成缩略图
                    if (!string.IsNullOrEmpty(guidGif))
                    {
                        ThumbGIF(guidGif, width, height);
                        EncodeGIF(guidGif, thumbnailPath, delays);
                    }
                }
                else
                {
                    //新建一个bmp图片
                    bitmap = new System.Drawing.Bitmap(towidth, toheight);

                    //新建一个画板
                    g = System.Drawing.Graphics.FromImage(bitmap);

                    //设置高质量插值法
                    g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;

                    //设置高质量,低速度呈现平滑程度
                    g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;

                    //清空画布并以透明背景色填充
                    g.Clear(Color.Transparent);

                    //在指定位置并且按指定大小绘制原图片的指定部分
                    g.DrawImage(originalImage, new Rectangle(0, 0, towidth, toheight),
                        new Rectangle(x, y, ow, oh),
                        GraphicsUnit.Pixel);


                    //以jpg格式保存缩略图
                    bitmap.Save(thumbnailPath, ImageFormat.Jpeg);
                }
            }
            finally
            {
                if (originalImageMs != null)
                {
                    originalImageMs.Close();
                }
                if (originalImage != null)
                {
                    originalImage.Dispose();
                }
                if (bitmap != null)
                {
                    bitmap.Dispose();
                }
                if (g != null)
                {
                    g.Dispose();
                }
            }
        }

        #endregion

        #region 降低图片质量 减小高质量图片大小
        /// <summary>
        /// 降低图片质量 减小高质量图片大小
        /// </summary>
        /// <param name="bytes">图片二进制</param>
        /// <param name="thumbnailPath">缩略图保存路径</param>
        /// <param name="width">宽</param>
        /// <param name="height">高</param>
        public static bool MakeLowThumbnail(byte[] bytes, string thumbnailPath)
        {
            MemoryStream originalImageMs = new MemoryStream(bytes, 0, bytes.Length);
            Image originalImage = null;
            Image bitmap = null;
            Graphics g = null;
            try
            {
                originalImage = Image.FromStream(originalImageMs);

                //Gif需要分别截取每一帧，然后再重新合成
                if (originalImage.RawFormat.Guid == ImageFormat.Gif.Guid)
                {
                    List<int> delays = new List<int>();
                    //按帧分割
                    string guidGif = DecodeGIF(originalImageMs, out delays);
                    //对每帧生成缩略图
                    if (!string.IsNullOrEmpty(guidGif))
                    {
                        if (!ThumbGIF(guidGif, originalImage.Width, originalImage.Height))
                        {
                            return false;
                        }
                        if (!EncodeGIF(guidGif, thumbnailPath, delays))
                        {
                            return false;
                        }
                    }
                }
                else
                {
                    //新建一个bmp图片
                    bitmap = new System.Drawing.Bitmap(originalImage.Width, originalImage.Height);

                    //新建一个画板
                    g = System.Drawing.Graphics.FromImage(bitmap);

                    //设置高质量插值法
                    g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Low;

                    //设置高质量,低速度呈现平滑程度
                    g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None;

                    //清空画布并以透明背景色填充
                    g.Clear(Color.Transparent);

                    //在指定位置并且按指定大小绘制原图片的指定部分
                    g.DrawImage(originalImage, new Rectangle(0, 0, originalImage.Width, originalImage.Height),
                        new Rectangle(0, 0, originalImage.Width, originalImage.Height),
                        GraphicsUnit.Pixel);

                    //以jpg格式保存缩略图
                    bitmap.Save(thumbnailPath, ImageFormat.Jpeg);
                }
                return true;
            }
            finally
            {
                if (originalImageMs != null)
                {
                    originalImageMs.Close();
                }
                if (originalImage != null)
                {
                    originalImage.Dispose();
                }
                if (bitmap != null)
                {
                    bitmap.Dispose();
                }
                if (g != null)
                {
                    g.Dispose();
                }
            }
        }
        #endregion

        #region 处理Gif动画

        //分割Gif
        public static string DecodeGIF(Stream inStream, out List<int> delays)
        {
            delays = new List<int>();
            string guid = Guid.NewGuid().ToString();
                
                if (inStream == null) { return string.Empty; }
                string outputPath = AppDomain.CurrentDomain.BaseDirectory + string.Format(@"\Files\Picture\Gif\{0}\Jpeg", guid);
                if (!Directory.Exists(outputPath))
                {
                    Directory.CreateDirectory(outputPath);
                }

                Image imgGif = Image.FromStream(inStream);
                //Create a new FrameDimension object from this image
                FrameDimension ImgFrmDim = new FrameDimension(imgGif.FrameDimensionsList[0]);

                //Determine the number of frames in the image
                //Note that all images contain at least 1 frame, 
                //but an animated GIF will contain more than 1 frame.
                int nFrameCount = imgGif.GetFrameCount(ImgFrmDim);

                // Save every frame into jpeg format
                for (int i = 0; i < nFrameCount; i++)
                {
                    imgGif.SelectActiveFrame(ImgFrmDim, i);
                    delays.Add(GetDelay(i, imgGif));
                    imgGif.Save(string.Format(@"{0}\{1}.jpg", outputPath, i), ImageFormat.Jpeg);
                }
                if (imgGif != null)
                {
                    imgGif.Dispose();
                }
            return guid;
        }

        public static int GetDelay(int i, Image img)
        {
            int delay = 10;
                for (int j = 0; j < img.PropertyIdList.Length; j++)//遍历帧属性
                {
                    if ((int)img.PropertyIdList.GetValue(j) == 0x5100)//如果是延迟时间
                    {
                        PropertyItem pItem = (PropertyItem)img.PropertyItems.GetValue(j);//获取延迟时间属性
                        byte[] delayByte = new byte[4];//延迟时间，以1/100秒为单位
                        delayByte[0] = pItem.Value[i * 4];
                        delayByte[1] = pItem.Value[1 + i * 4];
                        delayByte[2] = pItem.Value[2 + i * 4];
                        delayByte[3] = pItem.Value[3 + i * 4];
                        delay = BitConverter.ToInt32(delayByte, 0) * 10; //乘以10，获取到毫秒
                        break;
                    }
                }
            return delay;
        }

        public static bool ThumbGIF(string guidGIF, int width, int height)
        {
                string dirJPEG = AppDomain.CurrentDomain.BaseDirectory + string.Format(@"\Files\Picture\Gif\{0}\Jpeg", guidGIF);
                string[] Jpegs = Directory.GetFiles(dirJPEG);
                if (Jpegs.Length == 0)
                {
                    return false;
                }

                string dirHandledJPEG = AppDomain.CurrentDomain.BaseDirectory + string.Format(@"\Files\Picture\Gif\{0}\Handledjpeg", guidGIF);
                if (!Directory.Exists(dirHandledJPEG))
                {
                    Directory.CreateDirectory(dirHandledJPEG);
                }
                foreach (string item in Jpegs)
                {
                    MakeThumbnail(item, item.Replace(@"\Jpeg\", @"\Handledjpeg\"), width, height, false);
                }
                return true;
        }

        //合并Gif
        public static bool EncodeGIF(string guidGIF, string destGIF, List<int> delays)
        {
            try
            {
                string dirHandledJPEG = AppDomain.CurrentDomain.BaseDirectory + string.Format(@"\Files\Picture\Gif\{0}\Handledjpeg", guidGIF);
                string[] handledJPEGs = Directory.GetFiles(dirHandledJPEG);

                String outputFilePath = destGIF;
                AnimatedGifEncoder e = new AnimatedGifEncoder();
                e.Start(outputFilePath);
                //e.SetDelay(10);
                //-1:no repeat,0:always repeat
                e.SetRepeat(0);
                for (int i = 0, count = handledJPEGs.Length; i < count; i++)
                {
                    Image im = Image.FromFile(handledJPEGs[i]);
                    if ((i + 1) > delays.Count)
                    {
                        e.AddFrame(im, 10);
                    }
                    else
                    {
                        e.AddFrame(im, delays[i]);
                    }
                    if (im != null)
                    {
                        im.Dispose();
                    }
                }
                e.Finish();
                return true;
            }
            finally
            {
                Directory.Delete(AppDomain.CurrentDomain.BaseDirectory + string.Format(@"\Files\Picture\Gif\{0}", guidGIF), true);
            }
        }

        #endregion

    }
}
